#!/usr/bin/python
###################################################################################################                                                                                              
#                                                                                              
# DEVELOPERS : Luca Sanna                                                                        
# VERSIONE : 0.1                                                                                  
#                                                                                                                    
# E-MAIL: sanluca78@gmail.com                                                                                        
# COPYRIGHT: (c) 2015                                                                    
# PROGRAMMA: Py-Home-Slave
#This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.                                                                          
###################################################################################################
import time,sys,smtplib,ephem,datetime,pytz
from threading import Thread
from baseconfig import *
sys.path.append("%slib" %workingDir)
#db
from database import *
from ablib import Pin
from tools import *

#input
#PA24 - 'j4.11'
#PA25 - 'j4.13'
#PA26 - 'j4.15'
#PA27 - 'j4.17'
#PA28 - 'j4.19'
#PA29 - 'j4.21'
#PA0 - 'j4.23'
#PA8 - 'j4.25'

#output
#PC28 - 'j4.29'
#PC4 - 'j4.31'
#PC3 - 'j4.33'
#PC2 - 'j4.35'
#PC1 - 'j4.37'
#PC0 - 'j4.39'
#per la tenda il 1 rele va con il 3 tutte due a 1 
#il 2 rele va quando il 3 e a 0
class MyThread(Thread):
    time.sleep(1)
    db=Mydata()
    array=[]
    rel1=0
    rel2=0
    rel3=0
    rel4=0
    rel5=0
    rel6=0
   
    rele1 = Pin('J4.29','OUTPUT')
    rele2 = Pin('J4.31','OUTPUT')
    rele3 = Pin('J4.33','OUTPUT')
    rele4 = Pin('J4.35','OUTPUT')
    rele5 = Pin('J4.37','OUTPUT')
    rele6 = Pin('J4.39','OUTPUT')
    
    tent_c=0
    start_on=0

    def actualtime(self):
        actualTime=time.localtime()
        self.year=actualTime[0]
        self.month=actualTime[1]
        self.day=actualTime[2]
        self.hour=actualTime[3]
        self.minute=actualTime[4]
       
    def real_time(self):
        x=self.db.view_real_time()
        self.temp=x[1]
        self.umid=x[2]
        self.temp_d=x[3]
        self.pulse=x[4]
        self.rain=x[5]
        
    def view_boiler(self):
        a=self.db.view_boiler()
        self.temp_min=a[1]
        self.temp_imp=a[2]
        self.hourcont=a[3]
        self.start_hour=a[4]
        
    def status_tent(self):
        t = self.db.view_tent()
        self.open=t[1]
        self.close=t[2]
        self.half=t[3]
        self.mode=t[6]
        
    def status_operation(self):
        y = self.db.view_operation()
        self.tent=y[1]
        self.mini=y[2]
        self.boiler=y[3]
        self.normal=y[4]

    def power_rele_on(self,id):
        if id==1:
            self.rel1=1
        if id==2:
            self.rel2=1
        if id==3:
            self.rel3=1
        if id==4:
            self.rel4=1
        if id==5:
            self.rel5=1
        if id==6:
            self.rel6=1
   
    def power_rele_off(self,id):
        if id==1:
            self.rel1=0
        if id==2:
            self.rel2=0
        if id==3:
            self.rel3=0
        if id==4:
            self.rel4=0
        if id==5:
            self.rel5=0
        if id==6:
            self.rel6=0
       
    def status(self,status_id):
        self.actualtime()
        x = self.db.view_configure()
       
        for b in x:
            id=int(b[0])
            label=b[1]
            power=b[2]
            man=b[3]
            sunrise=b[4]
            calendar=b[5]
           
            if id==status_id:
                #logCritical("status %s" %status_id)

                if man == 1 and calendar == 0 and sunrise == 0:
                    self.manual(id)
                    #logCritical("manual id %s" %id)
                if man == 0 and calendar == 1 and sunrise == 0:
                    self.db_calendar(id,label)
                if man == 0 and calendar == 0 and sunrise == 1:
                    self.sunrise(id)

    def manual(self,manual_id):
       
        while True:
            try:
                self.actualtime()
                self.status_operation()
                #self.real_time()
                x = self.db.view_configure()
                #self.array=[]
                for b in x:
                    id=int(b[0])
                    power=int(b[2])
                    #pulse=b[6]
                   
                    if id==manual_id:
                        #logCritical("man %s %s" %(manual_id)
                       
                        if power==1:
                            self.power_rele_on(manual_id)
                            #if self.tent==1:
                                #self.tent_c=1
                        else:
                            self.power_rele_off(manual_id)
                        #if self.tent==1 and power==1:
                            #self.tent_c=1
                            #if id==1:
                                #self.db.update_configure('power',1,3)
                                #self.power_rele_on(3)
                            #if id==2:
                                #self.db.update_configure('power',0,3)
                                #self.power_rele_off(3)
                            #self.power_rele_on(manual_id)
                       

                break
            except Exception,e:
                logCritical("control manual %s" %e)
                time.sleep(1)
               
    def sunrise(self,sunrise_id):
        try:
            self.real_time()
            x = self.db.view_sunrise()
            llong=x[1]
            llat=x[2]
            zone1=x[3]
            duelamp = x[4]
            shifthour = x[5]
            shift_hour= int(shifthour)*60
           
            zone='%s' %zone1
       
            my_date = datetime.datetime.now(pytz.timezone(zone))
       
            o=ephem.Observer()
            o.lat= '%s' %llat
            o.long= '%s' %llong
            #logCritical("olat %s olong %s" %(o.lat,o.long))
            s=ephem.Sun()
            s.compute()
       
            fmt = "%H:%M"
       
            utc_sun= o.previous_rising(ephem.Sun()).datetime().replace(tzinfo=pytz.utc)
            utc_noon= o.previous_transit(ephem.Sun()).datetime().replace(tzinfo=pytz.utc)
            utc_set=o.previous_setting(ephem.Sun()).datetime().replace(tzinfo=pytz.utc)
       
            sunrise= utc_sun.astimezone(pytz.timezone(zone))
            noon=utc_noon.astimezone(pytz.timezone(zone))
            sunset= utc_set.astimezone(pytz.timezone(zone))
       
            newsunrise=sunrise.strftime(fmt)
            newnoon=noon.strftime(fmt)
            newsunset=sunset.strftime(fmt)

            actual=my_date.strftime(fmt)
            #logCritical("utc noon %s" %newnoon)
            #sunrise 2014-11-01 06:49:09.000005 noon 2014-11-01 11:52:59.000005 sunset 2014-11-01 16:56:13.000005
            campistart=newsunrise.split(':')
            campifra=newnoon.split(':')
            campiend=newsunset.split(':')
            campiactual=actual.split(':')
            ho,mo=campiend
            hme,mme=campifra
            hh,mm=campistart
            ha,ma=campiactual
            minon= (int(hh)*60)+int(mm)+int(shift_hour)
            minfra= (int(hme)*60)+int(mme)+int(shift_hour)
            minoff=(int(ho)*60)+int(mo)+int(shift_hour)
            minact=(int(ha)*60)+int(ma)+int(shift_hour)
            #logCritical("minon %s minoff %s minact %s" %(minon,minoff,minact))
            power=False
            #verifico se si usano due lampade differenti
           
            if duelamp==0:
               
                if minact >= minon and minact <= minoff:
                    power=True
                    #la prima lampada si accendera dal mattino al mezzogiorno, la seconda dal mezzogiorno alla sera    
            else:
                if minact >= minon and minact <= (minfra+60):
                    if sunrise_id==1:
                        power=True
                if minact >= minfra and minact <= minoff:
                    if sunrise_id==2:
                        power=True
       
            if power==True:
                self.power_rele_on(sunrise_id)
               
            elif power==False:
                self.power_rele_off(sunrise_id)
               
        except Exception,e:
            logCritical("control sunrise %s" %e)
            time.sleep(1)

     #il titolo deve avere le label
     #2014-0-30 formata data 15:00 formato ora
    def db_calendar(self,id,label):
        try:
            self.actualtime()
            #logCritical("calendar")
            indata="%s-%s-%s" %(self.year,self.month,self.day)
            zerodata="9999-00-00"
            x = self.db.view_calendar(indata,zerodata)
            self.arrayy=[]
            for b in x:
                title=str(b[3])
                sdate=(b[15])
                edate=(b[16])
                stime=(b[18])
                etime=(b[19])
                #da rivedere
                if (sdate == indata):# and edate == zerodata) or (sdate <= indata and edate >= indata):
                    #logCritical("sdate edate calendar")
                    campistart=stime.split(':')
                    campiend=etime.split(':')
                    ho,mo=campiend
                    hh,mm=campistart
                    if title== "%s" %label :
                    #minuti in 24H 1440
                        minon= (int(hh)*60)+int(mm)
                        minoff=(int(ho)*60)+int(mo)
                        self.arrayy.append([minon,minoff])
                   
            minact=(int(self.hour)*60)+int(self.minute)
            power=False
       
            for interval in self.arrayy:
                if minact>=interval[0] and minact <=interval[1]:
                    power=True

            if power==True:
                self.power_rele_on(id)
               
            elif power==False:
                self.power_rele_off(id)
               
        except Exception,e:
            logCritical("control calendar %s" %e)
            time.sleep(1)
            
    def hour_cont(self):
        tempo=time.time()
        hour=self.hourcont * 3600
        stop =self.start_hour + hour
        if hour > 0:
            if tempo > stop:  
                self.db.update_boiler('temp_imp',self.temp_min)
            
    def control_boiler(self):
        self.hour_cont()
        self.view_boiler()
        tempo=time.time()
        if self.temp_imp > self.temp_d:
            self.db.update_configure('power',1,1)
            if self.start_on==0:
                self.db.update_boiler('start_hour',tempo)
                self.start_on=1
        else:
            self.db.update_configure('power',0,1)
            self.start_on=0
            
    def run(self):
        z=0
        while True:
            z+=1
            self.real_time()
            self.actualtime()
            self.status_operation()
            if self.tent==1:
                self.status_tent()
            if self.boiler==1:
                self.view_boiler()
                self.control_boiler()
                
            self.status(int(z))

            self.rel= getattr(self, "rel%s" %z)
            self.rele= getattr(self, "rele%s" %z)
            
            if self.rel==1:
                self.rele.on()
                
                if self.tent:
                    if z==3:
                        if self.mode==0:
                            time.sleep(self.close)
                            self.db.update_tent_real('open',0,1)
                            self.db.update_tent_real('close',1,1)
                            self.db.update_tent_real('half',0,1)
                        else:
                            time.sleep(self.half)
                            self.db.update_tent_real('open',0,1)
                            self.db.update_tent_real('close',0,1)
                            self.db.update_tent_real('half',1,1)
                        self.db.update_configure('power',0,z)
                        self.db.update_configure('power',0,1)
                        
                        
                    if z==2:
                        if self.mode==0:
                            time.sleep(self.open)
                            self.db.update_tent_real('close',0,1)
                            self.db.update_tent_real('open',1,1)
                            self.db.update_tent_real('half',0,1)
                        else:
                            time.sleep(self.half)
                            self.db.update_tent_real('open',0,1)
                            self.db.update_tent_real('close',0,1)
                            self.db.update_tent_real('half',1,1)
                            
                        self.db.update_configure('power',0,z)
                        self.db.update_configure('power',0,3)
                            
            else:
                self.rele.off()
            
            if self.mini==1:
                if z==4:
                    z=0
            else:
                if z==6:
                    z=0
                    
            time.sleep(0.1)
